home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_066 / foogol / foogol.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  13KB  |  523 lines

  1. /*---------------------------------------------------------------------*\
  2. !                                                                       !
  3. !  fc.c  Compiler for FOOGOL IV -- version 4.2  Last change:1985-12-02  !
  4. !        Translates FOOGOL IV into VAX/UNIX assembler                   !
  5. !                                                                       !
  6. !    Written by Per Lindberg, QZ, Box 27322, 10254 Stockholm, Sweden.   !
  7. !                                                                       !
  8. !    This software is in the public domain. The Hacker Ethic applies.   !
  9. !    (A postcard from anyone who ports it would be appreciated.)        !
  10. !                                                                       !
  11. \*---------------------------------the-mad-programmer-strikes-again----*/
  12.  
  13. #define UNIX
  14.  
  15. #ifdef SARG10            /* Sargasso C (under TOPS10/20) peculiarities */
  16.   #strings low
  17.   #define _UNIXCON
  18. #endif
  19.  
  20. #include <stdio.h>
  21.  
  22. #define isupper(c) ((c) >= 'A' && (c) <= 'Z')
  23. #define tolower(c) ((c) - 'A' + 'a')
  24.  
  25. #define MAXTAB     25           /* Tweak these to your own liking  */
  26. #define MAXTOKEN   80
  27.  
  28. #define WHITESPACE  0           /* These could be turned into enum */
  29. #define NUMBER      1
  30. #define LETTER      2
  31. #define QUOTE       3
  32. #define SEMICOLON   4
  33. #define RANDOM      5
  34.  
  35. FILE *inf, *outf;
  36.  
  37. int labelcount = 0,
  38.     linecount  = 0,
  39.     debug      = 0;
  40.  
  41. char token[MAXTOKEN],
  42.      pending[MAXTOKEN],
  43.      keytab[MAXTAB][MAXTOKEN],
  44.      symtab[MAXTAB][MAXTOKEN],
  45.      *usage =
  46. #ifdef SARG10
  47.      "usage: '.run fc- [-debug] infile [outfile]'";
  48. #endif
  49. #ifdef UNIX
  50.      "usage: 'fc [-debug] infile [outfile]'";
  51. #endif
  52.  
  53. main(argc,argv) int argc; char *argv[]; {
  54.   if (argc < 2) error(usage);
  55.   if (*argv[1] == '-') { debug = 1; --argc; ++argv; }
  56.   if (argc < 2) error(usage);
  57.   openinfile(argv[1]);
  58.   openoutfile(argv[argc == 2 ? 1 : 2]);
  59.   init();
  60.   if (!PROGRAM()) error("Syntax error");
  61.   fclose(inf);
  62.   fclose(outf);
  63. }
  64.  
  65. char *defaultext(fname,ext,force) char *fname, *ext; int force; {
  66.   static char result[255];
  67.   char c, *point, *s = result;
  68.   strcpy(result,fname);
  69.   while (*s) ++s;
  70.   point = s;
  71.   while (c = *s, s > result && c != '.') --s;
  72.   if (c == '.') {                                /* some extention exists */
  73.     point = s;
  74.     if (!force) return result;            /* don't worry about what it is */
  75.   }
  76.   strcpy(point,ext);                 /* put default extention after point */
  77.   return result;
  78. }
  79.  
  80. openinfile(fname) char *fname; {
  81.   char *defaultext();
  82.   d("openinfile",defaultext(fname,".foo",0),"");
  83.   if ((inf = fopen(defaultext(fname,".foo",0),"r")) == NULL)
  84.     error2("Can't open infile", defaultext(fname,".foo",0));
  85. }
  86.  
  87. openoutfile(fname) char *fname; {
  88.   char *defaultext();
  89.   d("openoutfile",defaultext(fname,".s",1),"");
  90.   if ((outf = fopen(defaultext(fname,".s",1),"w")) == NULL)
  91.     error2("Can't open outfile", defaultext(fname,".s",1));
  92. }
  93.  
  94. init() {
  95.   int i;
  96.   d("init","","");
  97.   get2();
  98.   gettoken();
  99.   for (i = 0; i < MAXTAB; i++) keytab[i][0] = '\0';
  100. }
  101.  
  102. error(msg) char *msg; {
  103.   printf("\n\nFoo: %s", msg);
  104.   if (linecount) printf(" at line %d",linecount + 1);
  105.   printf("\n");
  106.   exit(1);
  107. }
  108.  
  109. error2(s1,s2) char *s1,*s2; {
  110.   static char msg[80];
  111.   sprintf(msg,"%s\"%s\"",s1,s2);
  112.   error(msg);
  113. }
  114.  
  115. lowcase(s) char *s; {
  116.   char c;
  117.   for (c = *s; c = *s; ++s) if (isupper(c)) *s = tolower(c);
  118. }
  119.  
  120. /* Basic I/O functions */
  121.  
  122. int out(line) char *line; {
  123.   char c, symb[MAXTOKEN], *subst(), *s = symb;
  124.   int printmode = 1, chmode = 1;
  125.   while(c = *line++) {
  126.     if (c == ' ') { if (chmode) putc('\t',outf);
  127.                     chmode = 0;
  128.     } else {
  129.       chmode = 1;
  130.       if (c != 39) { if (printmode) putc(c,outf);
  131.                      else           *s++ = c;
  132.       } else if (!printmode) {
  133.              *s = '\0';
  134.              if (*symb) fprintf(outf,"%s",subst(symb));
  135.              printmode = 1;
  136.            } else {
  137.              printmode = 0;
  138.              s = symb;
  139.            }
  140.     }
  141.   }
  142.   putc('\n',outf);
  143.   return 1;
  144. }
  145.  
  146. gettoken() {
  147.   strcpy(token,pending); get2();
  148.   if (!strcmp("/",token) && !strcmp("*",pending)) {
  149.     d("comment:",token,pending);
  150.     while (strcmp("*",token) || strcmp("/",pending)) {
  151.       strcpy(token,pending); get2();
  152.       d("        ",token,"");
  153.     }
  154.     strcpy(token,pending); get2();
  155.     strcpy(token,pending); get2();
  156.   }
  157. d("gettoken returning",token,pending);
  158. }
  159.  
  160. get2() {
  161.   int c0, c, typ, count = 1;
  162.   char *p = pending;
  163.   while((typ=type(c0=getc(inf))) == WHITESPACE) if (c0 == '\n') ++linecount;
  164.   if (c0 != EOF) *p++ = c0;
  165.   if (typ == QUOTE) {
  166.     while ((c = getc(inf)) != EOF && type(c) != QUOTE) {
  167.       if (++count == MAXTOKEN) error("String too long");
  168.       *p++ = c;
  169.     }
  170.     *p++ = '"';
  171.   }
  172.   else {
  173.     while ((type(c=getc(inf)) == typ
  174.             || typ == LETTER && type(c) == NUMBER)
  175.         && typ != RANDOM
  176.             && c != EOF) {
  177.       *p++ = c;
  178.       typ = type(c);
  179.       if (++count == MAXTOKEN) error("Too long input token");
  180.     }
  181.     ungetc(c,inf);
  182.   }
  183.   *p = '\0';  
  184. }
  185.  
  186. int type(c) int c; {
  187.   if (c == EOF) return -1;
  188.   if (c >= '0' && c <= '9') return(NUMBER);
  189.   if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') return(LETTER);
  190.   if (c == ' ' || c == '\t' || c == '\n') return(WHITESPACE); /*  */
  191.   if (c == '"') return (QUOTE);
  192.   if (c == ';') return (SEMICOLON);
  193.   return(RANDOM);
  194. }
  195.  
  196. /* Basic input matching functions */
  197.  
  198. int match(s) char *s; {
  199. d("match",token,s);
  200.   lowcase(token);
  201.   if (strcmp(s,token)) return 0;
  202.   gettoken();          return 1;
  203. }
  204.  
  205. int id(name) char *name; {
  206.   int t;
  207.   char c, *p = token;
  208.   d("id",token,name);
  209.   if (type(*p++) != LETTER) return 0;
  210.   while (c = *p++) {
  211.     t = type(c);
  212.     if (t != NUMBER && t != LETTER) return(0);
  213.   }
  214.   lowcase(token);
  215.   enter(name,token);
  216.   gettoken();
  217.   return(1);
  218. }
  219.  
  220. int number(name) char *name; {
  221.   char c, *p = token;
  222.   d("number",token,name);
  223.   while (c = *p++) if (type(c) != NUMBER) return(0);
  224.   enter(name,token);
  225.   gettoken();
  226.   return(1);
  227. }
  228.  
  229. int string(name) char *name; {
  230.   d("string",token,name);
  231.   if (*token != '"') return 0;
  232.   enter(name,token);
  233.   gettoken();
  234.   return 1;
  235. }
  236.  
  237. label(name) char *name; {
  238.   char result[6];
  239.   d("label ",name,"");
  240.   sprintf(result,"L%d",labelcount++);
  241.   enter(name,result);
  242. }
  243.  
  244. /* Internal symbol table */
  245.  
  246. enter(key,val) char *key, *val; {
  247.   int i;
  248.   d("enter ",val,key);
  249.   for (i = 0; i < MAXTAB; i++) {
  250.     if (keytab[i][0] == '\0') {
  251.       strcpy(keytab[i],key);
  252.       strcpy(symtab[i],val);
  253.       return;
  254.     }
  255.   }
  256.   error2("INTERNAL SYMTAB ENTER ERROR, can't enter ", val);
  257. }
  258.  
  259. int lookup(key) char *key; {
  260.   int i;
  261.   for (i = MAXTAB-1; i >= 0 ; i--) {
  262.     if (!strcmp(key,keytab[i])) {
  263.       d("lookup ",symtab[i],key);
  264.       return i;
  265.     }
  266.   }
  267.   error2("INTERNAL SYMTAB LOOKUP ERROR, can't find ", key);
  268. }
  269.  
  270. char *subst(key) char *key; {
  271.   return symtab[lookup(key)];
  272. }
  273.  
  274. remove(key) char *key; {
  275.   keytab[lookup(key)][0] = '\0';
  276. }
  277.  
  278. /* Syntax definition. This is the neat part! */
  279.  
  280. int PROGRAM() { d("PROGRAM",token,pending);
  281.   if (!match("begin"))    return 0;    out("      .text # # begin");
  282.                     out("      .align 1");
  283.                     out("      .globl  _main");
  284.                     out("_main:");
  285.                     out("      .word 0");
  286.   if (!OPT_DECLARATION()) return 0;
  287.   if (!STATEMENT())    return 0;
  288.   while (match(";"))
  289.     if (!STATEMENT())    return 0;
  290.   if (!match("end"))    return 0;    out("      ret   # # end");
  291.   return 1;
  292. }
  293.  
  294. int OPT_DECLARATION() { d("OPT_DECLARATION",token,pending);
  295.   if (DECLARATION()
  296.   && !match(";")) return 0;
  297.   return 1;
  298. }
  299.  
  300. int DECLARATION() { d("DECLARATION",token,pending);
  301.   if (!match("integer")) return 0;    out("     .data  1 # integer");
  302.   if (!ID_SEQUENCE())     return 0;    out("     .text");
  303.   return 1;
  304. }
  305.  
  306. int ID_SEQUENCE() { d("ID_SEQUENCE",token,pending);
  307.   if (!IDENTIFIER())    return 0;
  308.   while (match(","))
  309.     if (!IDENTIFIER())    return 0;
  310.   return 1;
  311. }
  312.  
  313. int IDENTIFIER() { d("IDENTIFIER",token,pending);
  314.   if (!id("X"))    return 0;        out("'X':  .long   0");
  315.                     remove("X");
  316.   return 1;
  317. }
  318.  
  319. int STATEMENT() { d("STATEMENT",token,pending);
  320.   return
  321.   IO_STATEMENT()
  322.   ||
  323.   WHILE_STATEMENT()
  324.   ||
  325.   COND_STATEMENT()
  326.   ||
  327.   BLOCK()
  328.   ||                     /* the order is important here */
  329.   ASSIGN_STATEMENT();
  330. }
  331.  
  332. int BLOCK() { d("BLOCK",token,pending);
  333.   if (!match("begin"))    return 0;    out(" # # # begin");
  334.   if (DECL_OR_ST())
  335.     while(match(";"))
  336.      if (!STATEMENT())    return 0;
  337.   if (!match("end"))    return 0;    out(" # # # end");
  338.   return 1;
  339. }
  340.  
  341. int DECL_OR_ST() { d("DECL_OR_ST",token,pending);
  342.   return
  343.   DECLARATION()
  344.   ||
  345.   STATEMENT();
  346. }
  347.  
  348. int IO_STATEMENT() { d("IO_STATEMENT",token,pending);
  349.   return
  350.   PRINTS_STATEMENT()
  351.   ||
  352.   PRINTN_STATEMENT()
  353.   ||
  354.   PRINT_STATEMENT();
  355. }
  356.  
  357. int PRINTS_STATEMENT() { d("PRINTS_STATEMENT",token,pending);
  358.   if (!match("prints")) return 0;
  359.   if (!match("("))    return 0;
  360.   if (!string("S"))    return 0;    label("Ls");
  361.                     out("      .data 1 # prints");
  362.                     out("'Ls': .asciz  'S'");
  363.                     out("      .text");
  364.                     out("      pushal   'Ls'");
  365.                     out("      calls   $1,_PRS");
  366.                     remove("S"); remove("Ls");
  367.   if (!match(")"))    return 0;
  368.   return 1;
  369. }
  370.  
  371. int PRINTN_STATEMENT() { d("PRINTN_STATEMENT",token,pending);
  372.   if (!match("printn")) return 0;
  373.   if (!match("("))    return 0;
  374.   if (!EXPRESSION())    return 0;    out("      pushl  r0 # printn");
  375.                     out("      calls   $1,_PRN");
  376.   if (!match(")"))    return 0;
  377.   return 1;
  378. }
  379.  
  380. int PRINT_STATEMENT() { d("PRINT_STATEMENT",token,pending);
  381.   if (!match("print"))    return 0;    out("      calls   $0,_PR # print");
  382.   return 1;
  383. }
  384.  
  385. int COND_STATEMENT() { d("COND_STATEMENT",token,pending);
  386.   if (!match("if"))    return 0;    label("Lt"); label("Le"); label("Lq");
  387.   if (!EXPRESSION())    return 0;    out("      tstl  r0 # if");
  388.   if (!match("then"))    return 0;    out("      bneq  'Lq' # then");
  389.                     out("      jmp   'Le'");
  390.                     out("'Lq':");
  391.   if (!STATEMENT())    return 0;    out("      jmp   'Lt'");
  392.                     out("'Le': #     # # else");
  393.   if (match("else"))
  394.     if (!STATEMENT())    return 0;    out("'Lt': #     # # endif");
  395.                     remove("Lt");remove("Le");remove("Lq");
  396.   return 1;
  397. }
  398.  
  399. int WHILE_STATEMENT() { d("WHILE_STATEMENT",token,pending);
  400.   if (!match("while"))    return 0;    label("Lw"); label("Lx"); label("Lv");
  401.                     out("'Lw': #     # # while");
  402.   if (!EXPRESSION())    return 0;    out("      tstl  r0");
  403.   if (!match("do"))    return 0;    out("      bneq  'Lv'");
  404.                                         out("      jmp   'Lx'");
  405.                                         out("'Lv': #     # # do");
  406.   if(!STATEMENT())    return 0;    out("      jmp   'Lw'");
  407.                     out("'Lx': #     # # endwhile");
  408.                     remove("Lw");remove("Lx");remove("Lv");
  409.   return 1;
  410. }
  411.  
  412. int ASSIGN_STATEMENT() { d("ASSIGN_STATEMENT",token,pending);
  413.   if (!id("Var"))    return 0;
  414.   if (!match(":"))    return 0;
  415.   if (!match("="))    return 0;
  416.   if (!EXPRESSION())    return 0;    out("    movl  r0,'Var' # 'Var':=");
  417.                     remove("Var");
  418.   return 1;
  419. }
  420.  
  421. int EXPRESSION() { d("EXPRESSION",token,pending);
  422.   if (!EXPR1())        return 0;
  423.   if (!OPT_RHS())    return 0;
  424.   return 1;
  425. }
  426.  
  427. int OPT_RHS() { d("OPT_RHS",token,pending);
  428.   return
  429.   RHS_EQ()
  430.   ||
  431.   RHS_NEQ()
  432.   ||
  433.   1;
  434. }
  435.  
  436. int RHS_EQ() { d("RHS_EQ",token,pending);
  437.   if (!match("="))    return 0;    label("L="); label("Ly");
  438.                     out("      pushl  r0 # =");
  439.   if (!EXPR1())        return 0;    out("      cmpl   (sp)+,r0");
  440.                     out("      beql   'L='");
  441.                     out("      movl   $0,r0");
  442.                     out("      jmp    'Ly'");
  443.                     out("'L=': movl   $1,r0");
  444.                     out("'Ly':");
  445.                     remove("L="); remove("Ly");
  446.   return 1;
  447. }
  448.  
  449. int RHS_NEQ() { d("RHS_NEQ",token,pending);
  450.   if (!match("#"))    return 0;    label("L#"); label("Lz");
  451.                     out("      pushl  r0 # <>");
  452.   if (!EXPR1())        return 0;    out("      cmpl   (sp)+,r0");
  453.                     out("      beql   'L#'");
  454.                     out("      movl   $1,r0");
  455.                     out("      jmp    'Lz'");
  456.                     out("'L#': movl   $0,r0");
  457.                     out("'Lz':");
  458.                     remove("L#"); remove("Lz");
  459.   return 1;
  460. }
  461.  
  462. int SIGNED_TERM() { d("SIGNED_TERM",token,pending);
  463.   return
  464.   PLUS_TERM()
  465.   ||
  466.   MINUS_TERM();
  467. }
  468.  
  469. int PLUS_TERM() { d("PLUS_TERM",token,pending);
  470.   if (!match("+"))    return 0;    out("      pushl  r0   # +term");
  471.   if (!TERM())        return 0;    out("      addl2  (sp)+,r0");
  472.   return 1;
  473. }
  474.  
  475. int MINUS_TERM() { d("MINUS_TERM",token,pending);
  476.   if (!match("-"))    return 0;    out("      pushl  r0   # -term");
  477.   if (!TERM())        return 0;    out("      subl3  r0,(sp)+,r0");
  478.   return 1;
  479. }
  480.  
  481. int TERM() { d("TERM",token,pending);
  482.   if (!PRIMARY())    return 0;
  483.   while (match("*")) {            out("      pushl  r0    # *");
  484.     if (!PRIMARY())    return 0;    out("      mull2  (sp)+,r0");
  485.   }
  486.   return 1;
  487. }
  488.  
  489. int PRIMARY() { d("PRIMARY",token,pending);
  490.   if (id("Z")) {            out("       movl 'Z',r0");
  491.                     remove("Z");
  492.     return 1;
  493.   }
  494.   if (number("Z")) {            out("       movl $'Z',r0");
  495.                     remove("Z");
  496.     return 1;
  497.   }
  498.   if (match("(")) {
  499.     if (!EXPRESSION())    return 0;
  500.     if (!match(")"))    return 0;
  501.     return 1;
  502.   }
  503.   return 0;
  504. }
  505.  
  506. int EXPR1() { d("EXPR1",token,pending);
  507.   if (!TERM())        return 0;
  508.   while(SIGNED_TERM());
  509.   return 1;
  510. }
  511.  
  512. /* And finally, the debug function... */
  513.  
  514. int d(s1,s2,s3) char *s1,*s2,*s3; {
  515.   if (debug) {
  516.     printf("%s",s1);
  517.     if (*s2) printf(" \"%s\"",s2);
  518.     if (*s3) printf(" \"%s\"",s3);
  519.     putchar('\n');
  520.   }
  521.   return 1;
  522. }
  523.